package org.example.ding.service;

import org.example.ding.dto.UserRegistrationDto;
import org.example.ding.dto.UserProfileDto;
import org.example.ding.entity.User;
import org.example.ding.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.Optional;

/**
 * 用户服务层
 */
@Service
@Transactional
public class UserService {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private PasswordEncoder passwordEncoder;

    /**
     * 用户注册
     */
    public User registerUser(UserRegistrationDto registrationDto) {
        // 检查用户名是否已存在
        if (userRepository.existsByUsername(registrationDto.getUsername())) {
            throw new RuntimeException("用户名已存在");
        }

        // 检查邮箱是否已存在
        if (userRepository.existsByEmail(registrationDto.getEmail())) {
            throw new RuntimeException("邮箱已被注册");
        }

        // 计算推荐的营养目标
        registrationDto.calculateRecommendedNutritionGoals();

        // 转换为User实体
        User user = registrationDto.toUser();
        
        // 加密密码
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        
        // 设置默认值
        user.setIsActive(true);

        // 保存用户
        return userRepository.save(user);
    }

    /**
     * 根据用户名或邮箱查找用户
     */
    @Transactional(readOnly = true)
    public Optional<User> findByUsernameOrEmail(String usernameOrEmail) {
        return userRepository.findByUsernameOrEmail(usernameOrEmail);
    }

    /**
     * 根据ID查找用户
     */
    @Transactional(readOnly = true)
    public Optional<User> findById(Long id) {
        return userRepository.findById(id);
    }

    /**
     * 根据用户名查找用户
     */
    @Transactional(readOnly = true)
    public Optional<User> findByUsername(String username) {
        return userRepository.findByUsername(username);
    }

    /**
     * 验证用户密码
     */
    @Transactional(readOnly = true)
    public boolean validatePassword(User user, String rawPassword) {
        return passwordEncoder.matches(rawPassword, user.getPassword());
    }

    /**
     * 更新用户个人信息
     */
    public User updateUserProfile(Long userId, UserProfileDto profileDto) {
        User user = userRepository.findById(userId)
            .orElseThrow(() -> new RuntimeException("用户不存在"));

        // 如果邮箱发生变化，检查新邮箱是否已被使用
        if (profileDto.getEmail() != null && !profileDto.getEmail().equals(user.getEmail())) {
            if (userRepository.existsByEmail(profileDto.getEmail())) {
                throw new RuntimeException("邮箱已被其他用户使用");
            }
        }

        // 更新用户信息
        profileDto.updateUser(user);

        return userRepository.save(user);
    }

    /**
     * 更新用户密码
     */
    public void updatePassword(Long userId, String oldPassword, String newPassword) {
        User user = userRepository.findById(userId)
            .orElseThrow(() -> new RuntimeException("用户不存在"));

        // 验证旧密码
        if (!passwordEncoder.matches(oldPassword, user.getPassword())) {
            throw new RuntimeException("原密码不正确");
        }

        // 更新密码
        user.setPassword(passwordEncoder.encode(newPassword));
        userRepository.save(user);
    }

    /**
     * 更新用户营养目标
     */
    public User updateNutritionGoals(Long userId, BigDecimal calories, BigDecimal protein, 
                                   BigDecimal carbs, BigDecimal fat) {
        User user = userRepository.findById(userId)
            .orElseThrow(() -> new RuntimeException("用户不存在"));

        if (calories != null) user.setDailyCaloriesGoal(calories);
        if (protein != null) user.setDailyProteinGoal(protein);
        if (carbs != null) user.setDailyCarbsGoal(carbs);
        if (fat != null) user.setDailyFatGoal(fat);

        return userRepository.save(user);
    }

    /**
     * 自动计算并更新营养目标
     */
    public User recalculateNutritionGoals(Long userId) {
        User user = userRepository.findById(userId)
            .orElseThrow(() -> new RuntimeException("用户不存在"));

        if (user.getHeight() == null || user.getWeight() == null || 
            user.getAge() == null || user.getGender() == null || 
            user.getActivityLevel() == null) {
            throw new RuntimeException("用户基本信息不完整，无法计算营养目标");
        }

        // 计算TDEE作为卡路里目标
        BigDecimal tdee = user.calculateTDEE();
        user.setDailyCaloriesGoal(tdee.setScale(0, BigDecimal.ROUND_HALF_UP));

        // 蛋白质：体重 * 1.6g
        BigDecimal protein = user.getWeight().multiply(new BigDecimal("1.6"))
            .setScale(0, BigDecimal.ROUND_HALF_UP);
        user.setDailyProteinGoal(protein);

        // 脂肪：总卡路里的27.5%
        BigDecimal fat = tdee.multiply(new BigDecimal("0.275"))
            .divide(new BigDecimal("9"), 0, BigDecimal.ROUND_HALF_UP);
        user.setDailyFatGoal(fat);

        // 碳水化合物：剩余卡路里
        BigDecimal proteinCalories = protein.multiply(new BigDecimal("4"));
        BigDecimal fatCalories = fat.multiply(new BigDecimal("9"));
        BigDecimal remainingCalories = tdee.subtract(proteinCalories).subtract(fatCalories);
        BigDecimal carbs = remainingCalories.divide(new BigDecimal("4"), 0, BigDecimal.ROUND_HALF_UP);
        user.setDailyCarbsGoal(carbs);

        return userRepository.save(user);
    }

    /**
     * 禁用用户账户
     */
    public void deactivateUser(Long userId) {
        User user = userRepository.findById(userId)
            .orElseThrow(() -> new RuntimeException("用户不存在"));
        
        user.setIsActive(false);
        userRepository.save(user);
    }

    /**
     * 激活用户账户
     */
    public void activateUser(Long userId) {
        User user = userRepository.findById(userId)
            .orElseThrow(() -> new RuntimeException("用户不存在"));
        
        user.setIsActive(true);
        userRepository.save(user);
    }

    /**
     * 获取所有激活用户
     */
    @Transactional(readOnly = true)
    public List<User> getAllActiveUsers() {
        return userRepository.findByIsActiveTrue();
    }

    /**
     * 统计激活用户数量
     */
    @Transactional(readOnly = true)
    public Long countActiveUsers() {
        return userRepository.countActiveUsers();
    }

    /**
     * 检查用户名是否可用
     */
    @Transactional(readOnly = true)
    public boolean isUsernameAvailable(String username) {
        return !userRepository.existsByUsername(username);
    }

    /**
     * 检查邮箱是否可用
     */
    @Transactional(readOnly = true)
    public boolean isEmailAvailable(String email) {
        return !userRepository.existsByEmail(email);
    }
}
